package es.unileon.prg2.patterns.composite;

import static org.junit.Assert.*;

import javax.swing.JOptionPane;

import org.junit.Before;
import org.junit.Test;

import es.unileon.prg2.patterns.handler.GenericId;

public class CompositeTests {

	private Component spain, cyl, leon, zamora, benavente;
	private Component ana, juan, maria, pedro, eva, antonio;
	int numberOfChildren;
	
	@Before
	public void setUp() throws CompositeException {
		// initial composites
		this.spain = new Country(new GenericId("Spain"));
		this.cyl = new Region(new GenericId("Castilla y Leon"));
		this.leon = new Province(new GenericId("Leon"));
		this.zamora = new Province(new GenericId("Zamora"));
		this.benavente = new Town(new GenericId("Benavente"));
		// initial leaves
		this.ana = new Citizen(new GenericId("Ana"));
		this.juan = new Citizen(new GenericId("Juan"));
		this.maria = new Citizen(new GenericId("Maria"));
		this.pedro = new Citizen(new GenericId("Pedro"));
		this.eva = new Citizen(new GenericId("Eva"));
		this.antonio = new Citizen(new GenericId("Antonio"));
		// building the tree
		this.spain.add(cyl);
		this.cyl.add(leon);
		this.cyl.add(zamora);
		this.zamora.add(benavente);
		// adding the leaves
		this.leon.add(ana);
		this.leon.add(juan);
		this.zamora.add(maria);
		this.zamora.add(pedro);
		this.benavente.add(eva);
		this.benavente.add(antonio);
		
		this.numberOfChildren = 0;
	}
	
	@Test
	public void testGetIdOK(){
		assertNotSame(this.spain.getId().toString(), new GenericId("Spai").toString());
	}

	@Test
	public void testAddOK() throws CompositeException{
		Component rosa = new Citizen("Rosa");
		assertEquals(this.spain.size(), 6);
		this.spain.add(rosa);
		assertEquals(this.spain.size(), 7);
		assertEquals(this.spain.search(rosa.getId()), rosa);		
	}
	
	@Test(expected=CompositeException.class)
	public void testAddNotOK() throws CompositeException{
		this.juan.add(ana);		
	}
	
	@Test
	public void testRemoveOK(){
		assertEquals(this.spain.size(), 6);		
		assertTrue(this.spain.remove(this.ana));
		assertEquals(this.spain.size(), 5);
		assertNull(this.spain.search(this.ana.getId()));
	}
	
	@Test
	public void testRemoveNotOK(){
		Component rosa = new Citizen("Rosa");
		assertFalse(this.spain.remove(rosa));
	}

	@Test
	public void testSearchOk(){
		// it works for composites from several places
		assertEquals(this.spain.search(this.spain.getId()), this.spain);
		assertEquals(this.cyl.search(this.leon.getId()), this.leon);
		assertEquals(this.cyl.search(this.benavente.getId()), this.benavente);		
		// it works for leaves wherever they are
		assertEquals(this.spain.search(this.ana.getId()), this.ana);
		assertEquals(this.spain.search(this.maria.getId()), this.maria);
		assertEquals(this.spain.search(this.eva.getId()), this.eva);
	}

	@Test
	public void testSearchNotOk(){
		assertNull(this.spain.search(new GenericId("Rosa")));
	}

	@Test
	public void testSize() throws CompositeException{
		// initial situation
		assertEquals(this.spain.size(), 6);
		assertEquals(this.cyl.size(), 6);
		assertEquals(this.leon.size(), 2);
		assertEquals(this.zamora.size(), 4);
		assertEquals(this.benavente.size(), 2);
		// adding a citizen to the root of the tree
		this.spain.add(new Citizen("Rosa"));
		assertEquals(this.spain.size(), 7);
		assertEquals(this.cyl.size(), 6);
		assertEquals(this.leon.size(), 2);
		assertEquals(this.zamora.size(), 4);
		assertEquals(this.benavente.size(), 2);
		// adding a citizen to a town (smallest composite)
		this.benavente.add(new Citizen("Alberto"));
		assertEquals(this.spain.size(), 8);
		assertEquals(this.cyl.size(), 7);
		assertEquals(this.leon.size(), 2);
		assertEquals(this.zamora.size(), 5);
		assertEquals(this.benavente.size(), 3);		
	}
	
	@Test
	public void testToString(){
		JOptionPane.showMessageDialog(null,this.spain.toString());
		assertEquals(this.spain.toString(),				
"	Country: Spain\n" +
"		Region: Castilla y Leon\n" +
"			Province: Leon\n" +
"					Citizen: Ana\n" +
"					Citizen: Juan\n" +
"			Province: Zamora\n" +
"				Town: Benavente\n" +
"					Citizen: Eva\n" +
"					Citizen: Antonio\n" +
"					Citizen: Maria\n" +
"					Citizen: Pedro\n");
	}

}